package org.gis.utils.dps;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyDescriptor;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

/**
 *
 * @author gus
 */
public class DynamicPropertySetBaseMap implements DynamicPropertySet
{
    private final static long serialVersionUID = 19861230123L;
    private transient  PropertyChangeSupport propertyChangeSupport = null;
    protected Map<String, DynamicProperty> propertiesMap;

    public DynamicPropertySetBaseMap()
    {
        propertiesMap = new TreeMap<String, DynamicProperty>();
    }

    public boolean contains( DynamicProperty property )
    {
        return propertiesMap.containsValue(property);
    }

    protected DynamicProperty findProperty( String name )
    {
        return propertiesMap.get(name);
    }

    public DynamicProperty getProperty( String name )
    {
        return findProperty(name);
    }

    /** @return type for the property with specified name. */
    public Class getType( String name )
    {
        DynamicProperty property = findProperty(name);
        return property != null ? property.getType() : null;
    }

    public PropertyDescriptor getPropertyDescriptor( String name )
    {
        DynamicProperty property = findProperty(name);
        if ( property != null )
        {
            return property.getDescriptor();
        }

        return null;
    }

    public <T> T getValue( String name )
    {
        DynamicProperty property = findProperty(name);
        return  (T)(property != null ? property.getValue() : null);
    }

    public Iterator nameIterator()
    {
        return propertiesMap.keySet().iterator();
    }

    public Map<String, DynamicProperty> asMap()
    {
        return Collections.unmodifiableMap(propertiesMap);
    }

    public void setValue( String name, Object value )
    {
        DynamicProperty property = findProperty(name);
        if ( property == null )
        {
            throw new IllegalArgumentException("Could not find property " + name + " in dynamic property set.");
        }

        Object oldValue = property.getValue();
        property.setValue(value);
        if ( hasListeners(name) )
        {
            firePropertyChange(new PropertyChangeEvent(this, name, oldValue, value));
        }
    }

    public void add( DynamicProperty property )
    {
        propertiesMap.put(property.getDescriptor().getName(), property);
        property.setParent(this);
    }

    public boolean remove( String name )
    {
        if ( propertiesMap.containsKey(name) )
        {
            DynamicProperty property = propertiesMap.get(name);
            property.setParent(null);
            propertiesMap.remove(name);

            return true;
        }

        return false;
    }

    public boolean replaceWith( String name, DynamicProperty prop )
    {
        if ( remove(name) )
        {
            add(prop);
            return true;
        }

        return false;
    }

    public void addPropertyChangeListener( PropertyChangeListener listener )
    {
        if ( propertyChangeSupport == null )
        {
            propertyChangeSupport = new PropertyChangeSupport(this);
        }

        propertyChangeSupport.addPropertyChangeListener(listener);
    }

    public void addPropertyChangeListener( String propertyName, PropertyChangeListener listener )
    {
        if ( propertyChangeSupport == null )
        {
            propertyChangeSupport = new PropertyChangeSupport(this);
        }

        propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
    }

    public void removePropertyChangeListener( PropertyChangeListener listener )
    {
        if ( propertyChangeSupport != null )
        {
            propertyChangeSupport.removePropertyChangeListener(listener);
        }

    }

    public void removePropertyChangeListener( String propertyName, PropertyChangeListener listener )
    {
        if ( propertyChangeSupport != null )
        {
            propertyChangeSupport.removePropertyChangeListener(propertyName, listener);
        }
    }

    public void firePropertyChange( String propertyName, Object oldValue, Object newValue )
    {
        if ( propertyChangeSupport != null )
        {
            propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
        }
    }

    public void firePropertyChange( PropertyChangeEvent evt )
    {
        if ( propertyChangeSupport != null )
        {
            propertyChangeSupport.firePropertyChange(evt);
        }
    }

    public boolean hasListeners( String propertyName )
    {
        if ( propertyChangeSupport == null )
        {
            return false;
        }

        return propertyChangeSupport.hasListeners(propertyName);
    }

    public int count()
    {
        return propertiesMap.size();
    }

    public boolean isEmpty()
    {
        return count() == 0;
    }

    @Override
    public String toString()
    {
        StringBuilder sb = new StringBuilder("[ ");
        for ( String key : propertiesMap.keySet() )
        {
            sb.append(key).append(", ");
        }
        sb.append(" ]");
        return sb.toString();
    }

    public Iterator<DynamicProperty> iterator()
    {
        return propertiesMap.values().iterator();
    }
}
